/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package muhnes.sizoo.controlador;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import muhnes.sizoo.dal.FabricaDAO;
import muhnes.sizoo.dal.PrivilegioDao;
import muhnes.sizoo.dal.SesionDao;
import muhnes.sizoo.dal.UsuarioDao;
import muhnes.sizoo.modelo.Privilegio;
import muhnes.sizoo.modelo.Rol;
import muhnes.sizoo.modelo.Sesion;
import muhnes.sizoo.modelo.Usuario;

/**
 * Clase controladora que se encarga de la vista de las sesion
 * 
 */
@ManagedBean(name = "sesionBean")
@SessionScoped
public class SesionBean implements Serializable {
    
    private String correo;
    private String contrasenya;
    private boolean autenticado;
    private Usuario usuario;
    private Map<Integer,Boolean> cachePrivilegios;

    public SesionBean() {
        usuario = new Usuario();
        cachePrivilegios = new HashMap<Integer,Boolean>();
    }
    
    /**
     * metodo para verificar los privilegios que tiene una sesion
     * @param evento 
     * @throws IOException tipo de excepcion que devuelve el metodo 
     */
    public void verificarSesion(ComponentSystemEvent evento) throws IOException {
        if( autenticado ) {
            FacesContext contexto = FacesContext.getCurrentInstance();
            String nombreContexto = contexto.getExternalContext().getRequestContextPath();
            String urlError = nombreContexto + "/paginas/protegido/cpanel.xhtml";
            contexto.getExternalContext().redirect(urlError);
        }
    }
    
    public String getCorreo() {
        return correo;
    }

    public void setCorreo(String correo) {
        this.correo = correo;
    }

    public String getContrasenya() {
        return contrasenya;
    }

    public void setContrasenya(String contrasenya) {
        this.contrasenya = contrasenya;
    }
    
    public boolean isAutenticado() {
        return autenticado;
    }

    public void setAutenticado(boolean autenticado) {
        this.autenticado = autenticado;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }
    
    /**
     * metodo para iniciar session 
     * @return 
     */
    public String iniciarSesion() {
        
        if( autenticado ) {
            return "/paginas/protegido/cpanel?faces-redirect=true";
        }
        
        FacesContext contexto = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) contexto.getExternalContext().getRequest();

        try {
            request.login( correo, contrasenya );
            autenticado = true;
            HttpSession sesionHttp = request.getSession();
            
            UsuarioDao usuarioDao = FabricaDAO.crearUsuarioDao();
            usuario = usuarioDao.buscarPorId( correo );
            
            PrivilegioDao privilegioDao = FabricaDAO.crearPrivilegioDao();
            List<Privilegio> privilegios = privilegioDao.buscarTodos();
            List<Privilegio> privilegiosAsignados = usuario.getPrivilegios();
            cachePrivilegios = new HashMap<Integer,Boolean>();
            for( Privilegio privilegio : privilegios ) {
                int opHash = privilegio.getOperacion().getNombre().hashCode();
                int obHash = privilegio.getObjeto().getNombre().hashCode();
                int hash = opHash + obHash;
                boolean permitido = privilegiosAsignados.contains( privilegio );    
                cachePrivilegios.put( hash, permitido );
            }
            
            Set<Rol> roles = new HashSet<Rol>();
            for( Rol rol : usuario.getRoles() ) {
                roles.add( rol );
            }
            
            SesionDao sesionDao = FabricaDAO.crearSesionDao();
            Sesion sesion = new Sesion();
            sesion.setUsuario( usuario );
            sesion.setInicio( Calendar.getInstance().getTime() );
            sesion.setFinalizacion( Calendar.getInstance().getTime() );
            sesion.setRoles( roles );
            sesionDao.guardar( sesion );
            
            int idsesion = sesion.getCodigosesion();

            usuarioDao.obtenerSesion().clear();
            sesionDao.obtenerSesion().clear();
            sesionHttp.setAttribute("usuario", usuarioDao.buscarPorId( correo ));
            sesionHttp.setAttribute("sesion", sesionDao.buscarPorId( idsesion ));
            
            return "/paginas/protegido/cpanel?faces-redirect=true";
        
        } catch ( ServletException e ) {
            autenticado = false;
            String error = "El usuario o la contraseña son incorrectos";
            contexto.addMessage(null, new FacesMessage( FacesMessage.SEVERITY_ERROR, error, error ));
            return "";
        }
    }
    
    /**
     * Metodo para cerrar sesion
     * @return string que indica si debe o no cerrar la sesiom
     */
    public String cerrarSesion() {
        if( autenticado ) {
            autenticado = false;
            correo = null;
            contrasenya = null;
            usuario = new Usuario();
            cachePrivilegios.clear();
            FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
            return "/inicio?faces-redirect=true";
        }
        else {
            return "";
        }
    }
    
    /**
     * Metodo para verificar los tipos de permiso que debe tener la sesion
     * @param nombreOperacion nombre de la operacion 
     * @param nombreObjeto nombre del objeto
     * @return objeto de tipo boolean que indica si tiene permisos 
     */
    public boolean verificarPermiso( String nombreOperacion, String nombreObjeto ) {       
        int hash = nombreOperacion.hashCode() + nombreObjeto.hashCode();
        return cachePrivilegios.containsKey( hash ) && cachePrivilegios.get( hash );
    }

}


